import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';

/// HTTP 服务类 - 类似 Axios 的功能
/// 实现拦截器、错误处理、取消请求等功能
class HttpService {
  static const String _baseUrl = 'https://api.gitcode.com/api/v5';
  static const String _tokenKey = 'gitcode_access_token';
  
  late Dio _dio;
  String? _accessToken;
  
  HttpService() {
    _dio = Dio(BaseOptions(
      baseUrl: _baseUrl,
      connectTimeout: const Duration(seconds: 30),
      receiveTimeout: const Duration(seconds: 30),
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    ));
    
    _setupInterceptors();
    _loadToken();
  }
  
  /// 设置拦截器
  void _setupInterceptors() {
    // 请求拦截器 - 自动添加认证信息
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        // 自动添加认证 token
        if (_accessToken != null && _accessToken!.isNotEmpty) {
          // 支持两种认证方式：Authorization Bearer 和 PRIVATE-TOKEN
          options.headers['Authorization'] = 'Bearer $_accessToken';
          options.headers['PRIVATE-TOKEN'] = _accessToken;
        }
        
        // 打印请求信息（开发环境）
        print('🚀 Request: ${options.method} ${options.uri}');
        if (options.data != null) {
          print('📦 Request Data: ${options.data}');
        }
        
        return handler.next(options);
      },
      onResponse: (response, handler) {
        // 响应拦截器 - 统一处理响应
        print('✅ Response: ${response.statusCode} ${response.requestOptions.uri}');
        
        // 检查速率限制
        final rateLimitRemaining = response.headers.value('x-ratelimit-remaining');
        if (rateLimitRemaining != null) {
          final remaining = int.tryParse(rateLimitRemaining);
          if (remaining != null && remaining < 10) {
            print('⚠️ Rate limit warning: $remaining requests remaining');
          }
        }
        
        return handler.next(response);
      },
      onError: (error, handler) {
        // 错误拦截器 - 统一错误处理
        print('❌ Error: ${error.type} - ${error.message}');
        
        if (error.response != null) {
          final statusCode = error.response!.statusCode;
          final statusMessage = error.response!.statusMessage;
          
          switch (statusCode) {
            case 400:
              print('❌ Bad Request: 请求参数错误');
              break;
            case 401:
              print('❌ Unauthorized: 认证失败，请检查 token');
              break;
            case 403:
              print('❌ Forbidden: 没有权限执行该操作');
              break;
            case 404:
              print('❌ Not Found: 请求的资源不存在');
              break;
            case 429:
              print('❌ Too Many Requests: 请求频率超过限制');
              // 可以在这里实现重试逻辑
              break;
            case 500:
              print('❌ Internal Server Error: 服务器内部错误');
              break;
            default:
              print('❌ Error: $statusCode $statusMessage');
          }
        } else if (error.type == DioExceptionType.connectionTimeout ||
                   error.type == DioExceptionType.receiveTimeout) {
          print('❌ Timeout: 请求超时');
        } else if (error.type == DioExceptionType.connectionError) {
          print('❌ Connection Error: 网络连接错误');
        }
        
        return handler.next(error);
      },
    ));
  }
  
  /// 从本地存储加载 token
  Future<void> _loadToken() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      _accessToken = prefs.getString(_tokenKey);
    } catch (e) {
      print('Error loading token: $e');
    }
  }
  
  /// 设置访问令牌
  Future<void> setAccessToken(String token) async {
    _accessToken = token;
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString(_tokenKey, token);
    } catch (e) {
      print('Error saving token: $e');
    }
  }
  
  /// 清除访问令牌
  Future<void> clearAccessToken() async {
    _accessToken = null;
    try {
      final prefs = await SharedPreferences.getInstance();
      await prefs.remove(_tokenKey);
    } catch (e) {
      print('Error clearing token: $e');
    }
  }
  
  /// 获取当前 token
  String? get accessToken => _accessToken;
  
  /// GET 请求
  Future<Response<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    try {
      return await _dio.get<T>(
        path,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  /// POST 请求
  Future<Response<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    try {
      return await _dio.post<T>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  /// PUT 请求
  Future<Response<T>> put<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    try {
      return await _dio.put<T>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  /// DELETE 请求
  Future<Response<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    try {
      return await _dio.delete<T>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  /// 处理错误
  HttpException _handleError(DioException error) {
    if (error.response != null) {
      return HttpException(
        statusCode: error.response!.statusCode ?? 0,
        message: error.response!.statusMessage ?? 'Unknown error',
        data: error.response!.data,
      );
    } else {
      String message = 'Network error';
      if (error.type == DioExceptionType.connectionTimeout) {
        message = 'Connection timeout';
      } else if (error.type == DioExceptionType.receiveTimeout) {
        message = 'Receive timeout';
      } else if (error.type == DioExceptionType.connectionError) {
        message = 'Connection error';
      }
      return HttpException(
        statusCode: 0,
        message: message,
      );
    }
  }
}

/// HTTP 异常类
class HttpException implements Exception {
  final int statusCode;
  final String message;
  final dynamic data;
  
  HttpException({
    required this.statusCode,
    required this.message,
    this.data,
  });
  
  @override
  String toString() {
    return 'HttpException: $statusCode - $message';
  }
}

